package org.opens.util;

/**
 * @author qiaoxuan
 * @date 2023/4/9 13:06
 */
public class ByteUtil {

    public static final int B = 0;
    public static final int BIT = 1;

    public static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /**
     * 将16进制字符串转换为byte数组
     * 例如"7F7F"->[127, 127], 可以发现, 4位字符串转换为byte数组后变为了2个长度的数组, 是因为一个byte占用8bit, 而一个16进制数占4bit, 所
     * 以两个16进制数对应1个byte, 因此长度除以2
     * 注意:
     * - 传入的字符串如果不是偶数位的会在前面补0
     *
     * @param hex 待转换的16进制字符串
     * @return byte数组
     */
    public static byte[] hexStringToByteArray(String hex) {
        // 如果长度为奇数, 则在前面补0
        hex = hex.length() % 2 == 1 ? "0" + hex : hex;

        int len = hex.length();

        // 思考16进制与byte所占用bit的长度即可换算
        // 注意: 16进制数总是双位的, 例如不会出现单独的F, 而是0F
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 因为一个byte占用8bit, 而一个16进制数占4bit, 所以两个16进制数对应1个byte, 因此长度除以2
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }

        return data;
    }

    /**
     * 功能: 将byte数组转换为16进制字符串
     *
     * @param b 待转换的byte数组
     * @return 对应的16进制数
     */
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            // 对小于A的数补0
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            stringBuilder.append(hex.toUpperCase());
        }
        return stringBuilder.toString();
    }

    /**
     * 将byte数转换为16进制字符串
     *
     * @param b 待转换的byte数
     * @return 转换后得16进制数
     */
    public static String byteToHexString(byte b) {
        // & 0xFF 会将负数前面的1全部去掉, 因为byte负数前面所补的1都是无效的
        return Integer.toHexString(b & 0xFF).toUpperCase();
    }

    /**
     * 将byte转换为16进制字符串
     * @param b 待转换的byte数
     * @return  转换后得16进制数
     */
    public static String byteToHexString2(byte b) {
        char[] chars = new char[2];
        chars[0] = HEX_DIGITS[(b >>> 4) & 0X0F];
        chars[1] = HEX_DIGITS[b & 0X0F];
        return new String(chars);
    }

    /**
     * 将byte数组转换为16进制字符串
     * @param bytes 待转换的byte数组
     * @return  转换后的16进制字符串
     */
    public static String byteArrayToHexString2(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0, len = bytes.length; i < len; i++) {
            sb.append(byteToHexString2(bytes[i]));
        }
        return sb.toString();
    }

    /**
     * 将16进制数转为byte数
     *
     * @param hex 待转换的16进制数
     * @return 转换后得byte数
     */
    public static byte hexStringToByte(String hex) {
        return Byte.valueOf(hex, 16);
    }

    /**
     * 功能: 将int数转换为16进制数
     *
     * @param num 待转换的int数
     * @return 转换后的16进制数
     */
    public static String intToHexString(int num) {
        return Integer.toHexString(num).toUpperCase();
    }

    /**
     * 功能: short类型转换为byte数组
     *
     * @param value 待转换的值
     * @return 转换后得byte数组
     */
    public static byte[] intToByteArray(int value) {
        return hexStringToByteArray(intToHexString(value));
    }

    /**
     * 功能: 将16进制数转换为int数
     *
     * @param hex 待转换的16进制数
     * @return 转换后的int数
     */
    public static int hexStringToInt(String hex) {
        return Integer.valueOf(hex, 16);
    }

    /**
     * 功能: long数转换为16进制数
     *
     * @param value long数
     * @return 转换后得16进制数
     */
    public static String longToHexString(long value) {
        return Long.toHexString(value).toUpperCase();
    }

    /**
     * 功能: long类型转换为byte数组
     *
     * @param value 待转换的值
     * @return 转换后得byte数组
     */
    public static byte[] longToByteArray(long value) {
        return hexStringToByteArray(longToHexString(value));
    }

    /**
     * 功能: 将16进制数转换为long数
     *
     * @param hex 待转换的16进制数
     * @return 转换后的long数
     */
    public static long hexStringToLong(String hex) {
        return Long.valueOf(hex, 16);
    }

    /**
     * 功能: short数转16进制字符串
     *
     * @param value short数
     * @return 转换后得16进制字符串
     */
    public static String shortToHexString(short value) {
        return Integer.toHexString(value).toUpperCase();
    }


    /**
     * 功能: short类型转换为byte数组
     *
     * @param value 待转换的值
     * @return 转换后得byte数组
     */
    public static byte[] shortToByteArray(short value) {
        return hexStringToByteArray(shortToHexString(value));
    }

    /**
     * 将16进制数转为short数
     *
     * @param hex 待转换的16进制数
     * @return 转换后得short数
     */
    public static short hexStringToShort(String hex) {
        return Short.valueOf(hex, 16);
    }

    /**
     * 将2进制字符串转换为16进制字符串
     * 备注:
     * - 无法转换负数的2进制字符串, Integer.valueOf只能转换无符号数
     *
     * @param binaryString 2进制字符串
     * @return 16进制字符串
     */
    public static String binaryStringToHexString(String binaryString) {
        return longToHexString(Long.valueOf(binaryString, 2));
    }

    /**
     * 将16禁止字符串转换为二进制字符串
     *
     * @param hexString 待转换16进制字符串
     * @return 转换后得2进制字符串
     */
    public static String hexStringToBinaryString(String hexString) {
        return Long.toBinaryString(hexStringToLong(hexString));
    }

    /**
     * 超长16进制字符串转换为2进制字符串
     * @param hex   待转换16进制字符串
     * @return  转换后得2进制字符串
     */
    public static String longUnsignedHexStringToBinaryString(String hex) {
        byte[] bytes = hexStringToByteArray(hex);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(unsignedBinaryStringZeroFill(Integer.toBinaryString(bytes[i] & 0xFF), 1, B));
        }
        return sb.toString();
    }

    /**
     * 功能: 对无符号16进制字符串进行补全
     *
     * @param hexString 无符号16进制字符串
     * @param fillLen   补全后得长度
     * @return 补全后得16进制字符串
     */
    public static String unsignedHexStringZeroFill(String hexString, int fillLen) {
        if (hexString.length() >= fillLen) {
            return hexString;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < fillLen - hexString.length(); i++) {
            sb.append("0");
        }
        sb.append(hexString);
        return sb.toString();
    }

    /**
     * 根据Byte或者Bit来补零16进制数
     *
     * @param hexString 待补零的16进制数
     * @param fillLen   补零长度
     * @param unit      补零单位
     * @return 补零后得16进制字符串
     */
    public static String unsignedHexStringZeroFill(String hexString, int fillLen, int unit) {
        int realFillLen = 0;
        if (unit == B) {
            realFillLen = fillLen * 2;
        } else if (unit == BIT) {
            realFillLen = (fillLen / 4) + (fillLen % 4 == 0 ? 0 : 1);
        } else {
            throw new IllegalArgumentException("参数错误!");
        }
        return unsignedHexStringZeroFill(hexString, realFillLen);
    }

    /**
     * 无符号2进制字符串填充0.
     * @param binaryString 2进制字符串
     * @param fillLen   补全长度
     * @param unit  补全单位
     * @return
     */
    public static String unsignedBinaryStringZeroFill(String binaryString, int fillLen, int unit) {
        int realFillLen = 0;
        if (unit == B) {
            realFillLen = fillLen * 8;
        } else if (unit == BIT) {
            realFillLen = fillLen;
        } else {
            throw new IllegalArgumentException("参数错误!");
        }
        return unsignedBinaryStringZeroFill(binaryString, realFillLen);
    }

    /**
     * 按位填充2进制字符串
     * @param binaryString  待填充字符串
     * @param fillLen   填充后长度
     * @return  填充后得字符串
     */
    public static String unsignedBinaryStringZeroFill(String binaryString, int fillLen) {
        if (binaryString.length() >= fillLen) {
            return binaryString;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < fillLen - binaryString.length(); i++) {
            sb.append("0");
        }
        sb.append(binaryString);
        return sb.toString();
    }


    /**
     * 对16进制字符串根据Byte进行切割
     * @param hexString 切割字符串
     * @param start 开始byte
     * @param end   结束byte
     * @return  切割后得字符串
     */
    public static String hexStringSubstringByByte(String hexString, int start, int end) {
        return hexString.substring(start * 2, end * 2);
    }

    /**
     * 将16进制字符串转换为带符号int; 认定最高位为符号位
     * @param hexString 16进制数
     * @return  带符号的int数
     */
    public static int hexStringToSignedInt(String hexString) {
        int len = 32 - hexString.length() * 4;
        return Integer.valueOf(hexString, 16) << len >> len;
    }

    private static final String[] hexIndexToBinaryStringArray = new String[] {
            "0000",
            "0001",
            "0010",
            "0011",
            "0100",
            "0101",
            "0110",
            "0111",
            "1000",
            "1001",
            "1010",
            "1011",
            "1100",
            "1101",
            "1110",
            "1111"
    };

    public static String hexStringToBinaryStringFixedLength(String hexString) {
        String[] hexArr = hexString.split("");
        StringBuilder builder = new StringBuilder();
        for (String item : hexArr) {
            builder.append(hexIndexToBinaryStringArray[Integer.valueOf(item, 16)]);
        }
        return builder.toString();
    }


}